iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
自我挑戰組

數位影像處理系列 第 23

[Day 23]閥值化、分水嶺與GrabCut

  • 分享至 

  • xImage
  •  

今天來介紹最後四種常用的影像分割,分別為閥值化、適應性閥值化、分水嶺分割、GrabCut分割。


1.影像閥值化

影像分割的目的在偵測目標物件。若數位影像的物件與背景,在強度(或灰階)的分佈,具有良好的可分離性,則可以使用影像閥值化的技術,藉以分割出目標物件與其背景。

**影像閥值化(Image Thresholding)**可以定義為:

https://ithelp.ithome.com.tw/upload/images/20220930/20152370BgIEnzJu9A.png

由於在此使用的閥直T,是直接套用於整張影像,因此又稱為全域閥值化(Global Thresholding)。數位影像的閥值化可被視為統計學上的分類問題,與機率學中的**貝氏定理(Bayes Rule)**相關。如何選取理想的閥直,自然也成為是否可以成功分割目標物件的主要因素。

為了自動選取理想的值,Otsu提了一種方法,目的是根據像素強度(或灰階)的分佈,使**類別間的變異數(Between-Class Variance)**達到最大值。

影像閥值化的程式碼如下:

import numpy as np
import cv2
import math

img1 = cv2.imread("D:\Desktop\IThome\house.jpg", 0)
thresh, img2 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

cv2.imshow("Original", img1)
cv2.imshow("After", img2)

cv2.waitKey()
cv2.destroyAllWindows()
結果如下:

https://ithelp.ithome.com.tw/upload/images/20220930/20152370frSxtFCzgS.png
由於數位影像中的物件與其背景的強度(或灰階)具有可分離性,因此可以使用影像閥值化的方法分割。結果影像包含物件與背景,物件通常是定義為Binary-1、背景則是定義為Binary-0;分別用255與0的值儲存


2.適應性閥值化

上面介紹的全域閥值化,由於只使用單一閥值,因此在許多情況下,例如光暗漸層、打光不均等,可能會無法成功分割物件,此時就可採用**適應性閥值(Adaptive Threshold)**。

適應性閥值化技術中,每個像素所採用的閥值是根據該像素的局部區域而定,具有適應性。OpenCV提供兩種適應性閥化的選取方法,分別為:**(1)平均法(Mean)**與**(2)高斯法(Gaussian)**。適應性閥值是根據局部區域的平均值或高斯濾波的結果而定,主要的參數為局部區域大小。

程式碼如下:
import numpy as np
import cv2
import math

img1 = cv2.imread("D:/Desktop/IThome/alpha.bmp", 0)
thresh, img2 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
img3 = cv2.adaptiveThreshold(img1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 0)
img4 = cv2.adaptiveThreshold(img1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 0)
cv2.imshow("Original", img1)
cv2.imshow("Global", img2)
cv2.imshow("Gaussian", img3)
cv2.imshow("Mean", img4)

cv2.waitKey()
cv2.destroyAllWindows()

結果如下:
https://ithelp.ithome.com.tw/upload/images/20220930/20152370DohnMx2zHp.png
如上圖,左上角為原始影像,有些字母的字元有光暗的差別,使用全域閥值就會造成右上角的結果,有些字母無法全部被分離,若改用適應性閥值,就會如左下角(Mean),或右下角(Gaussian)有較理想的結果。


3.分水嶺分割

**分水嶺(Watershed)**是根據灰階影像定義的一種轉換,可以用來進行影像分割。顧名思義,分水嶺演算法是將灰階影像視為高低起伏的地形,灰階較大的區域視為山丘或山峰,灰階較小的區域則視為山谷。一開始,我們在較低的山谷(灰階的局部最小值)灌水,兩個相鄰的貧地在持續灌水到滿時,則在相鄰的交界處建立分水嶺,整個過程是持續灌水與不斷地將分水嶺築高,直到水位超過最高的山頂為止。此時,建立的分水嶺就是影像分割區域的邊緣。

OpenCV提供分水嶺函式,稱為Watershed,需事先定義灌水的起點,稱為漂記。礙於篇幅原因,因此程式碼就不再這贅述,讀者可自行至OpenCV官方查詢。

4.GrabCut分割

GrabCut演算法算是另一種影像分割技術,計算方式比分水嶺演算法複雜。Grabcut演算法目的是希望透過少許的使用者互動過程,即可得到不錯的影像分割效果。

GrabCut演算法是基於**流量網路(Flow Network)**,主要是根據數位影像中的像素建構一個圖,流量網路同時包含一個Source與一個Sink,分別為流量的起點與終點,背景像素則與Sink節點相連,透過流量的最小切割(Minimum Cut)演算法,切割之後,與Source節點相連的像素即是前景,與Sink節點相連則是背景。(註:關於最大流量-最小切割定理與Fork-Fulkerson演算法內容眾多,有興趣的讀者可自行查詢)

GrabCut演算法步驟說明如下:
(1) 首先根據使用者定義一個矩形框,大致包含準備分割的前景物件。GrabCut會根據舉行框進行初步的影像分割,採用的方法是利用**高斯混和模型(Gaussian Mixture Models)**
(2) 若是矩形框初步分割的結果不理想,可利用人工方式分別標記必然是前景的區域與必然是背景的區域。
(3) GrabCut演算法容許持續加入標記,直到影像分割結果令人滿意為止

OpenCV提供GrabCut的影像分割函式:
`cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode])`
  • img:輸入的色彩影像

  • mask:遮罩影像

  • rect:矩形框,包含準備分割的前景物件

  • bgdModel:前景模型的暫存陣列

  • fgdModel:背景模型的暫存陣列

  • iterCount:迭代次數

  • mode:處理模式

    礙於篇幅關係,GrabCut的程式碼就不再此贅述,但GrabCut是一個很有趣的演算法,背後牽涉的原理較多,因此若有時間,了解高斯模型與流量網路是比較好的喔。


上一篇
[Day 22]直線與圓形偵測
下一篇
[Day 24]影像壓縮
系列文
數位影像處理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言